from rest_framework import serializers
from .models import OauthQQ
from users.models import User
import re
from django_redis import get_redis_connection
from meiduo_mall.libs.qq_sdk import OAuthQQHelper
from meiduo_mall.utils.jwt_token import generate_jwt_token


class QQBindSerializer(serializers.Serializer):
    # 定义属性
    # 1.接收的属性
    mobile = serializers.CharField(max_length=11, write_only=True)
    password = serializers.CharField(
        min_length=8,
        max_length=20,
        error_messages={
            'min_length': '密码必须为8-20个字符',
            'max_length': '密码必须为8-20个字符'
        },
        write_only=True
    )
    sms_code = serializers.IntegerField(write_only=True)
    access_token = serializers.CharField(max_length=1000, write_only=True)

    # 2.响应的属性
    id = serializers.IntegerField(read_only=True)
    username = serializers.CharField(read_only=True)
    token = serializers.CharField(read_only=True)

    # 定义验证方法
    def validate(self, attrs):
        mobile = attrs.get('mobile')
        password = attrs.get('password')
        sms_code = attrs.get('sms_code')
        access_token = attrs.get('access_token')

        # 验证手机号格式
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            raise serializers.ValidationError('手机号格式错误')

        # 验证短信：请求报文中包含用户填写的，从redis中读取之前生成的
        redis_cli = get_redis_connection('smscode')
        sms_code_redis = redis_cli.get('sms_' + mobile)
        if not sms_code_redis:
            raise serializers.ValidationError('验证码已经过期')
        if sms_code != int(sms_code_redis):
            raise serializers.ValidationError('验证码错误')

        # 验证openid:是否修改，是否过期
        openid = OAuthQQHelper.check_openid_token(access_token)
        if openid is None:
            raise serializers.ValidationError('授权已过期，请重新授权')
        attrs['openid'] = openid

        # 手机号是否已经存在
        try:
            user = User.objects.get(mobile=mobile)
        except:
            # 2.手机号不存在，则新建用户对象，新建qq对象
            attrs['user'] = None
        else:
            # 1.手机号存在，则判断密码是否正确
            # 1.2如果密码不正确则抛异常
            if not user.check_password(password):
                raise serializers.ValidationError('手机号已经被使用，密码错误')
            else:
                # 1.1密码正确则新建qq对象
                attrs['user'] = user

        return attrs

    # 定义create()方法
    def create(self, validated_data):
        # 验证通过后的数据，会构造成一个字典validated_data，这个字典为validate()方法返回的字典
        user = validated_data.get('user')
        if user is None:
            # 创建用户对象
            mobile = validated_data.get('mobile')
            password = validated_data.get('password')
            user = User.objects.create_user(username=mobile, mobile=mobile, password=password)

        # 绑定
        openid = validated_data.get('openid')
        qq = OauthQQ.objects.create(openid=openid, user=user)

        # 状态保持，使用jwt
        user.token = generate_jwt_token(user)

        return user
